/*
 * @Copyright: Copyright (c) 2030 吴周海
 * @Author: wzh200x@126.com
 * @Date: 2025-10-13 11:20:00
 * @LastEditors: wzh200x@126.com
 * @LastEditTime: 2025-10-13 11:45:20
 * @FilePath: \gogamewebserver\goGameWebServer\internal\middlewares\jwtAuth.go
 * @Description: JWT鉴权中间件，支持必需/可选令牌模式；校验 LoginUUID 与缓存一致性
 */
package middlewares

import (
	"fmt"
	"strings"

	"goGameWebServer/internal/jwt"
	"goGameWebServer/internal/manager/cachemanager"

	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
)

// MiddlewareJWT 返回一个可配置的 JWT 中间件
// requireToken 为 true 表示该路由必须携带合法令牌；为 false 表示可选（携带则解析，不携带也放行）。
func MiddlewareJWT(requireToken bool) ghttp.HandlerFunc {
	return func(r *ghttp.Request) {
		authHeader := r.Header.Get("Authorization")
		token := parseBearerToken(authHeader)

		if token == "" {
			if requireToken {
				// 必需但未提供，直接返回错误
				r.SetParam("code", 401)
				r.SetParam("message", "未授权：缺少令牌")
				r.SetParam("data", g.Map{
					"error": "missing_token",
				})
				r.Response.WriteJsonExit(g.Map{
					"code":    401,
					"message": "未授权：缺少令牌",
					"data":    g.Map{"error": "missing_token"},
				})
				return
			}
			// 可选模式，无令牌直接放行
			r.Middleware.Next()
			return
		}

		// 解析令牌
		claims, err := jwt.ParseToken(token)
		if err != nil {
			if requireToken {
				r.SetParam("code", 401)
				r.SetParam("message", "未授权：令牌无效")
				r.SetParam("data", g.Map{
					"error": err.Error(),
				})
				r.Response.WriteJsonExit(g.Map{
					"code":    401,
					"message": "未授权：令牌无效",
					"data":    g.Map{"error": err.Error()},
				})
				return
			}
			// 可选模式，忽略错误继续
			r.Middleware.Next()
			return
		}

		// 校验 LoginUUID 与缓存一致性
		cacheKey := fmt.Sprintf("auth:%s:%d", claims.Username, claims.UserID)
		cacheResp, cacheErr := cachemanager.ManagerCache().Get(cacheKey)
		if cacheErr != nil || claims.LoginUUID == "" || claims.LoginUUID != cacheResp {
			if requireToken {
				r.SetParam("code", 401)
				r.SetParam("message", "未授权：登录状态已失效")
				r.SetParam("data", g.Map{
					"error": "login_uuid_mismatch_or_expired",
				})
				r.Response.WriteJsonExit(g.Map{
					"code":    401,
					"message": "未授权：登录状态已失效",
					"data":    g.Map{"error": "login_uuid_mismatch_or_expired"},
				})
				return
			}
			// 可选模式，令牌无效则不注入上下文，继续
			r.Middleware.Next()
			return
		}

		// 注入用户信息到上下文，供后续处理器使用
		r.SetParam("userID", claims.UserID)
		r.SetParam("username", claims.Username)
		r.SetParam("loginUUID", claims.LoginUUID)

		// 放行
		r.Middleware.Next()
	}
}

// MiddlewareJWTRequired 需要令牌的中间件（必须合法）
func MiddlewareJWTRequired(r *ghttp.Request) {
	MiddlewareJWT(true)(r)
}

// MiddlewareJWTOptional 可选令牌的中间件（不阻断）
func MiddlewareJWTOptional(r *ghttp.Request) {
	MiddlewareJWT(false)(r)
}

// parseBearerToken 从 Authorization 头中解析 Bearer 令牌
func parseBearerToken(authHeader string) string {
	if authHeader == "" {
		return ""
	}
	// 格式：Authorization: Bearer <token>
	parts := strings.SplitN(authHeader, " ", 2)
	if len(parts) != 2 || strings.ToLower(parts[0]) != "bearer" {
		return ""
	}
	return strings.TrimSpace(parts[1])
}

/*
使用示例（路由注册）：

// 需要令牌的接口
group := s.Group("/api")
group.Middleware(middlewares.MiddlewareJWTRequired)
group.ALL("/secure", controller.Secure)

// 不需要令牌的接口（可选令牌）
group2 := s.Group("/public")
group2.Middleware(middlewares.MiddlewareJWTOptional)
group2.ALL("/info", controller.Info)
*/
